﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Jenvin.Library.DBUtility.SqlDom
{
  /// <summary>
  /// 模板表达式
  /// </summary>
  public class TemplateExpression : SqlExpression
  {

    private string _template;

    public string Template
    {
      get { return _template; }
    }
    private SqlExpression[] _parameters;

    public SqlExpression[] Parameters
    {
      get { return _parameters; }
    }

    private TemplateExpression( string template, SqlExpression[] parameters )
    {
      _template = template;
      _parameters = parameters;
    }

    /// <summary>
    /// 创建一个模板表达式
    /// </summary>
    /// <param name="template">表达式模板</param>
    /// <param name="parameters">模板参数</param>
    public static TemplateExpression CreateTemplateExpression( string template, params object[] parameters )
    {

      string _template = template.Replace( "{...}", ParseParameterListSymbol( parameters.Length ) );

      _template = FormatTemplate( _template, parameters );

      SqlExpression[] _parameters = new SqlExpression[parameters.Length];
      for ( int i = 0; i < parameters.Length; i++ )
      {
        SqlExpression expression = parameters[i] as SqlExpression;
        if ( expression != null )
          _parameters[i] = expression;
        else
          _parameters[i] = new ParameterExpression( parameters[i] );
      }

      return new TemplateExpression( _template, _parameters );
    }

    private static string ParseParameterListSymbol( int amount )
    {
      StringBuilder builder = new StringBuilder();

      bool begin = true;
      for ( int i = 0; i < amount; i++ )
      {
        if ( !begin )
          builder.Append( " , " );
        builder.Append( "{" + i + "}" );
        begin = false;
      }

      return builder.ToString();
    }

    private static string FormatTemplate( string template, object[] parameters )
    {
      return FormatUtility.FormatRegexNum.Replace( template, delegate( Match match )
      {
        int index = int.Parse( match.Groups["index"].ToString() );
        if ( index >= parameters.Length )
          throw new ArgumentOutOfRangeException( "template" );

        string format = null;
        if ( match.Groups["format"].Success )
          format = match.Groups["format"].Value;

        if ( format != null )
          return FormatUtility.FormatObject( parameters[index], format, "" );
        else
          return match.ToString();

      }
      );
    }
  }
}
